package org.rainbowinverted.charging.device.connect.bl.server.handler;

import cn.hutool.core.util.HexUtil;
import com.dix.codec.bkv.BKV;
import com.dix.codec.bkv.KV;
import com.dix.codec.bkv.UnpackBKVResult;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.rainbowinverted.charging.device.connect.bl.server.message.in.BlDeviceGunChargeInfoIn;
import org.rainbowinverted.charging.device.connect.bl.server.message.in.BlDeviceGunInfoIn;
import org.rainbowinverted.charging.device.connect.bl.server.message.in.BlDeviceStatusReportIn;
import org.rainbowinverted.charging.device.connect.bl.server.message.out.BlDeviceStatusReportOut;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 设备事件上报处理器
 *
 * @author huaiping
 */
@Slf4j
@Component
@ChannelHandler.Sharable
@AllArgsConstructor
public class BlDeviceStatusReportHandler extends BlAbstractHandler<List<BlDeviceStatusReportIn>, BlDeviceStatusReportOut> {

    private BlGunInfoMessageHandler blGunInfoMessageHandler;

    @Override
    public void write(BlDeviceStatusReportOut message, BKV bkv) {
        addAck(bkv, message.getAck());
    }

    @Override
    public void read(ChannelHandlerContext channelHandlerContext, BKV bkv) {
        // 设备信息
        Long deviceNo = getDeviceNo(bkv);
        // 多充电枪会上报多个0x5c kv
        List<KV> bkvItems = bkv.getItems();
        List<BlDeviceStatusReportIn> deviceStatusReportList = new ArrayList<>(2);
        for (KV bkvItem : bkvItems) {
            if (bkvItem.getNumberKey() == 0x5c) {
                // 充电枪信息
                UnpackBKVResult subBkv = BKV.unpack(bkvItem.getValue());
                BKV gunInfoBkv = subBkv.getBKV();
                BlDeviceGunInfoIn gunInfo = blGunInfoMessageHandler.gunInfoDecode(gunInfoBkv);
                BlDeviceGunChargeInfoIn gunChargeInfo = blGunInfoMessageHandler.gunPowerInfoDecode(gunInfoBkv);
                // 电压，定点1位小数，单位V
                int voltage = Integer.parseInt(HexUtil.encodeHexStr(gunInfoBkv.get(0x55).getValue()), 16);
                // 急停按钮状态，0---正常 1---按下
                byte emergenceStatus = Byte.parseByte(HexUtil.encodeHexStr(gunInfoBkv.get(0x74).getValue()), 16);
                // 漏电流，定点三位小数，单位A
                int leakCurrent = Integer.parseInt(HexUtil.encodeHexStr(gunInfoBkv.get(0x75).getValue()), 16);
                // CP电压，定点一位小数，单位A
                int cpVoltage = Integer.parseInt(HexUtil.encodeHexStr(gunInfoBkv.get(0x76).getValue()), 16);
                BlDeviceStatusReportIn eventReportDTO = BlDeviceStatusReportIn.builder()
                        .deviceNo(deviceNo)
                        .gunInfo(gunInfo)
                        .gunChargeInfo(gunChargeInfo)
                        .voltage(voltage * 10)
                        .cpVoltage(cpVoltage * 10)
                        .leakCurrent(leakCurrent / 10)
                        .emergenceStatus(emergenceStatus == 0x01)
                        .reportTime(LocalDateTime.now()).build();
                deviceStatusReportList.add(eventReportDTO);
            }
        }
        Long serialNo = getSerialNo(bkv);
        complete(serialNo, deviceStatusReportList);
        // 发送确认命令
        channelHandlerContext.writeAndFlush(new BlDeviceStatusReportOut(deviceNo, serialNo, (byte) 0x01));
        log.info("device status report info : {}", deviceStatusReportList);
    }
}
